home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / PROG_TOO / C027B.ZIP / HCC / OUT.C < prev    next >
Text File  |  1990-03-30  |  12KB  |  726 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    out.c
  12.  *
  13.  *    Code generation output routines.
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include "param.h"
  18. #include "nodes.h"
  19. #include "flags.h"
  20. #include "bstok.h"
  21. #include "tytok.h"
  22. #include "gen.h"
  23.  
  24. #ifdef dLibs
  25. #include <ctype.h>
  26. #endif
  27.  
  28. #if MMCC
  29. overlay "pass2"
  30. #endif
  31.  
  32. #if CC68
  33. FILE *fopen();
  34. #endif
  35.  
  36. #if NEEDBUF
  37. char my_obuf[BUFSIZ];
  38. #endif
  39.  
  40. #define T_SEG    0
  41. #define D_SEG    1
  42. #define B_SEG    2
  43.  
  44. #define TO_TEXT    to_seg(T_SEG)
  45. #define TO_DATA    to_seg(D_SEG)
  46. #define TO_BSS    to_seg(B_SEG)
  47.  
  48. #define isareg(np)    ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  49.  
  50. extern FILE *output;
  51.  
  52. static int in_seg;
  53. static int lblnum;
  54. static int dat_size;
  55.  
  56. out_start(s)
  57. char *s;
  58. {
  59.     char *scopy(), *outs;
  60.     register int len;
  61.  
  62.     outs = scopy(s);
  63.     len = strlen(outs);
  64.     if (len >= 2 && outs[len-2] == '.' &&
  65.             tolower(outs[len-1]) == 'c') {
  66.         outs[len-1] = 's';
  67.         output = fopen(outs, "w");
  68.         if (output == NULL)
  69.             fatals("Cant open", outs);
  70. #if NEEDBUF
  71.         setbuf(output, my_obuf);
  72. #endif
  73.     } else
  74.         output = stdout;
  75.     sfree(outs);
  76.  
  77.     in_seg = -1;
  78.     lblnum = 0;
  79.     dat_size = 0;
  80. }
  81.  
  82. out_end()
  83. {
  84.     if (output != stdout)
  85.         fclose(output);
  86. }
  87.  
  88. static char *sg_go[] = {
  89.     ".text",
  90.     ".data",
  91.     ".bss"
  92. };
  93.  
  94. to_text()
  95. {
  96.     TO_TEXT;
  97. }
  98.  
  99. to_seg(sg)
  100. {
  101.     if (sg == in_seg)
  102.         return;
  103.     fprintf(output, "\t%s\n", sg_go[sg]);
  104.     in_seg = sg;
  105. }
  106.  
  107. o_aln(x)
  108. {
  109.     if (x && (dat_size & 1)) {
  110.         dat_size++;
  111.         TO_DATA;
  112.         fprintf(output, "\t.even\n");
  113.     }
  114. }
  115.  
  116. char *rnms[] = {
  117.     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
  118.     "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
  119. };
  120.  
  121. char *regnm(n)
  122. {
  123.     return rnms[n];
  124. }
  125.  
  126. char *
  127. init_str(n)
  128. {
  129.     char *s;
  130.  
  131.     switch (n) {
  132.     case 1:
  133.         s = ".dc.b";    break;
  134.     case 2:
  135.         s = ".dc.w";    break;
  136.     default:
  137.         s = ".dc.l";    break;
  138.     }
  139.     return s;
  140. }
  141.  
  142. tlen(n)
  143. {
  144.     switch (n) {
  145.     case 1:
  146.         return 'b';
  147.     case 2:
  148.         return 'w';
  149.     default:
  150.         return 'l';
  151.     }
  152. }
  153.  
  154. o_vinit(tp, xp)
  155. NODEP tp, xp;
  156. {
  157.     fprintf(output, "\t%s\t", init_str((int)tp->t_size));
  158.     dat_size += tp->t_size;
  159.  
  160.     p2_expr(&xp);
  161.     asn_chk(tp, xp);
  162.     to_init(xp, tp);
  163.  
  164.     fputc('\n', output);
  165. }
  166.  
  167. to_init(np, typ)
  168. NODEP np, typ;
  169. {
  170.     NODEP tp;
  171.  
  172.     tp = allocnode();
  173.     tp->e_token = TCONV;
  174.     tp->n_tptr = typ;
  175.     tp->n_flags |= N_COPYT;
  176.     tp->n_left = np;
  177.     tp->e_type = E_UNARY;
  178.     strcpy(tp->n_name, "i cast");
  179.  
  180.     genx(tp, FORINIT);
  181. }
  182.  
  183. out_argreg(np)
  184. NODEP np;
  185. {
  186.     fprintf(output, "\tmove.%c\t%d(a6),%s\n",
  187.         tlen((int)np->n_tptr->t_size), (int)np->e_offs,
  188.         regnm(np->e_rno));
  189. }
  190.  
  191. out_fstart(np)
  192. NODEP np;
  193. {
  194.     extern    int    pflag;
  195.  
  196.     TO_TEXT;
  197.     if (np->e_sc != K_STATIC) {
  198.         fprintf(output, "\t.globl\t");
  199.         und_nnm(np);
  200.         fputc('\n', output);
  201.     }
  202.     und_nnm(np);
  203.     fprintf(output, ":\n");    
  204.  
  205.     if (pflag) {
  206.         int    tlab = new_lbl();
  207.  
  208.         TO_BSS;
  209.         fprintf(output, "L%d:\t.ds.l\t1\n", tlab);
  210.         TO_TEXT;
  211.         fprintf(output, "\tmove.l\t#");
  212.         und_nnm(np);
  213.         fprintf(output, ",a0\n");
  214.  
  215.         fprintf(output, "\tmove.l\t#L%d,a1\n", tlab);
  216.         fprintf(output,    "\tjsr\tmcount\n");
  217.     }
  218. }
  219.  
  220. static char rbuf[30];
  221.  
  222. char *
  223. regstr(regs)
  224. {
  225.     int lod, hid, loa, hia;
  226.     register i;
  227.     char *bp = rbuf;
  228.  
  229.     lod = 999;
  230.     hid = -1;
  231.     for (i=DRV_START; i<=DRV_END; i++)
  232.         if (regs & (1<<i)) {
  233.             if (i < lod)  lod = i;
  234.             if (i > hid)  hid = i;
  235.         }
  236.     loa = 999;
  237.     hia = -1;
  238.     for (i=ARV_START; i<=ARV_END; i++)
  239.         if (regs & (1<<i)) {
  240.             if (i < loa)  loa = i;
  241.             if (i > hia)  hia = i;
  242.         }
  243.     if (lod < 999) {
  244.         if (lod != hid)
  245.             sprintf(bp, "d%d-d%d", lod, hid);
  246.         else
  247.             sprintf(bp, "d%d", lod);
  248.         if (loa < 999) {
  249.             bp += strlen(rbuf);
  250.             *bp++ = '/';
  251.         }
  252.     }
  253.     if (loa < 999) {
  254.         if (loa != hia)
  255.             sprintf(bp, "a%d-a%d", loa-AREG, hia-AREG);
  256.         else
  257.             sprintf(bp, "a%d", loa-AREG);
  258.     }
  259.     return rbuf;
  260. }
  261.  
  262. out_fend(regs, lsize)
  263. long lsize;
  264. {
  265.     if (lsize < 0x7fff)
  266.         fprintf(output, "\tlink\ta6,#-%d\n", (int)lsize);
  267.     else
  268.         fprintf(output, "\tlink\ta6,#0\n\tsub.l\t#%ld,sp\n",
  269.             lsize);
  270.     if (regs)
  271.         fprintf(output, "\tmovem.l\t%s,-(sp)\n", regstr(regs));
  272. }
  273.  
  274. out_fret(regs, strl)
  275. {
  276.     if (regs)
  277.         fprintf(output, "\tmovem.l\t(sp)+,%s\n", regstr(regs));
  278.     if (strl)
  279.         fprintf(output, "\tmove.l\t#L%d,a0\n", strl);
  280.     fprintf(output, "\tunlk\ta6\n\trts\n");
  281. }
  282.  
  283. out_fs(strl, size)
  284. long size;
  285. {
  286.     TO_BSS;
  287.     def_lbl(strl);
  288.     fprintf(output, "\t.ds.w\t%ld\n", size/2);
  289. }
  290.  
  291. out_gv(np, isbss)
  292. register NODEP np;
  293. {
  294.     long sz;
  295.     char c;
  296.  
  297.     if (np->e_sc == K_STATIC) {
  298.         np->e_offs = lblnum++;
  299.     }
  300.     if (np->e_sc != K_EXTERN) {
  301.         to_seg(isbss ? B_SEG : D_SEG);
  302.         if (np->e_sc != K_STATIC) {
  303.             fprintf(output, "\t.globl\t");
  304.             out_nm(np);
  305.             fputc('\n', output);
  306.         }
  307.         if (isbss) {
  308.             if (np->e_sc == K_STATIC) {
  309.                 out_nm(np);
  310.                 sz = np->n_tptr->t_size;
  311.                 c = 'b';
  312.                 if (np->n_tptr->t_aln) {
  313.                     c = 'w';
  314.                     sz /= 2;
  315.                 }
  316.                 fprintf(output, ":\t.ds.%c\t%ld\n", c, sz);
  317.             } else {
  318.                 fprintf(output, "\t.comm\t");
  319.                 out_nm(np);
  320.                 sz = np->n_tptr->t_size;
  321.                 if (sz & 1) sz++;  /* ALCYON hack */
  322.                 fprintf(output, ",%ld\n", sz);
  323.             }
  324.         } else {
  325.             out_nm(np);
  326.             fprintf(output, ":\n");
  327.         }
  328.     }
  329. }
  330.  
  331. new_lbl()
  332. {
  333.     return lblnum++;
  334. }
  335.  
  336. def_lbl(l)
  337. {
  338.     fprintf(output, "L%d:\n", l);
  339. }
  340.  
  341. out_br(l)
  342. {
  343.     if (l < 0)
  344.         error("bad branch");
  345.     else
  346.         fprintf(output, "\tbra\tL%d\n", l);
  347. }
  348.  
  349. static char *bnm[] = {
  350.     "",
  351.     "beq",
  352.     "bne",
  353.     "blt",
  354.     "bge",
  355.     "ble",
  356.     "bgt",
  357.     "bra",
  358.     "nop",
  359.     "bcs",
  360.     "bcc",
  361.     "bls",
  362.     "bhi"
  363. };
  364.  
  365. out_b(key, l)
  366. {
  367.     if (key != B_NO)
  368.         fprintf(output, "\t%s\tL%d\n", bnm[key], l);
  369. }
  370.  
  371. out_bnol(key)
  372. {
  373.     fprintf(output, "\t%s\t", bnm[key]);
  374. }
  375.  
  376. out_d0cmp(x)
  377. {
  378.     fprintf(output, "\tcmp.w\t#%d,d0\n", x);
  379. }
  380.  
  381. out_d0sub(x)
  382. {
  383.     fprintf(output, "\tsub.w\t#%d,d0\n", x);
  384. }
  385.  
  386. out_tlbl(l)
  387. {
  388.     fprintf(output, "\t.dc.l\tL%d\n", l);
  389. }
  390.  
  391. out_tsw()
  392. {
  393.     fprintf(output, "\text.l\td0\n");
  394.     fprintf(output, "\tasl.l\t#2,d0\n");
  395.     fprintf(output, "\tmove.l\t4(pc,d0.l),a0\n");
  396.     fprintf(output, "\tjmp\t(a0)\n");
  397. }
  398.  
  399. out_nm(np)
  400. NODEP np;
  401. {
  402.     if (np->e_sc == K_STATIC)
  403.         fprintf(output, "L%d", (int)np->e_offs);
  404.     else
  405.         und_nnm(np);
  406. }
  407.  
  408. out_zi(tp)
  409. NODEP tp;
  410. {
  411.     char *s;
  412. /*
  413.     switch (tp->t_token) {
  414.     case K_FLOAT:
  415.         fprintf(output, "\t.float\t0.0\n");    return;
  416.     case K_DOUBLE:
  417.         fprintf(output, "\t.double\t0.0\n");    return;
  418.     }
  419. */
  420.     dat_size += tp->t_size;
  421.     s = init_str((int)tp->t_size);
  422.     fprintf(output, "\t%s\t0\n", s);
  423. }
  424.  
  425. o_nz(sz, aln)
  426. long sz;
  427. {
  428.     dat_size += sz;
  429.     if (aln) {
  430.         if (sz & 1)
  431.             fprintf(output, "\t.ds.b\t1\n");
  432.         sz >>= 1;
  433.         fprintf(output, "\t.ds.w\t%ld\n", sz);
  434.     } else {
  435.         fprintf(output, "\t.ds.b\t%ld\n", sz);
  436.     }
  437. }
  438.  
  439. dumpstrs(np)
  440. NODEP np;
  441. {
  442.     TO_DATA;
  443. more:
  444.     if (np == NULL)
  445.         return;
  446.     fprintf(output, "L%d:", (int)np->g_offs);
  447.     out_scon(np);
  448.     np = np->n_next;
  449.     goto more;
  450. }
  451.  
  452. int see_esc;
  453.  
  454. out_scon(np)
  455. NODEP np;
  456. {
  457.     int len = 0;
  458.  
  459.     if (np == NULL)
  460.         return 0;
  461.     see_esc = 0;
  462. more:
  463.     if (np->n_name[0]) {
  464.         fprintf(output, "\t.dc.b\t");
  465.         len += out_str(np->n_name);
  466.         putc('\n', output);
  467.     }
  468.     np = np->n_nmx;
  469.     if (np)
  470.         goto more;
  471.  
  472.     fprintf(output, "\t.dc.b\t0\n");
  473.     len++;
  474.     dat_size += len;
  475.     return len;
  476. }
  477.  
  478. out_str(s)
  479. char *s;
  480. {
  481.     int len;
  482.     register c;
  483.  
  484.     len = 0;
  485.     for ( ; c = *s; s++) {
  486.         if (see_esc) {    /* allow null */
  487.             c--;
  488.             see_esc = 0;
  489.         } else if (c == 1) {
  490.             see_esc = 1;
  491.             continue;
  492.         }
  493.         if (len)
  494.             putc(',', output);
  495.         out_1c(c);
  496.         len++;
  497.     }
  498.     return len;
  499. }
  500.  
  501. out_asm(np)
  502. NODEP np;
  503. {
  504.     putc('\t', output);
  505. more:
  506.     fprintf(output, "%s", np->n_name);    /* no \0 or \1 please! */
  507.     np = np->n_nmx;
  508.     if (np)
  509.         goto more;
  510.     putc('\n', output);
  511. }
  512.  
  513. und_nnm(np)
  514. NODEP np;
  515. {
  516.     fputc('_', output);
  517.     fput_nnm(np);
  518. }
  519.  
  520. out_1c(c)
  521. char c;
  522. {
  523.     fprintf(output, "$%x", c & 0xff);
  524. }
  525.  
  526. outcode(np)
  527. register NODEP np;
  528. {
  529.     NODEP tp;
  530.  
  531.     if (np == NULL) return;
  532.  
  533.     switch (np->g_type) {
  534.     case EV_NONE:
  535.         break;
  536.     case EV_RL:
  537.         outcode(np->n_right);
  538.         outsub(np->g_betw, np);
  539.         /* fall through */
  540.     case EV_LEFT:
  541.         outcode(np->n_left);
  542.         break;
  543.     case EV_LR:
  544.     case EV_LRSEP:
  545.         outcode(np->n_left);
  546.         outsub(np->g_betw, np);
  547.         /* fall through */
  548.     case EV_RIGHT:
  549.         outcode(np->n_right);
  550.         break;
  551.     default:
  552.         printf("bad eval %d ", np->g_type);
  553.     }
  554.     if (np->n_flags & N_COPYT)    /* g_code is a char * */
  555.         outsub(np->g_code, np);
  556.     else                /* g_code is a list of nodes */
  557.         for (tp=np->g_code; tp != NULL; tp = tp->g_code)
  558.             outsub(tp->n_name, np);
  559. }
  560.  
  561. outsub(cp, np)
  562. register char *cp;
  563. register NODEP np;
  564. {
  565.     register char c;
  566.  
  567.     if (cp == NULL) return;
  568.     while (c = *cp++)
  569.         if (c == '<')
  570.             out_let(*cp++, np->n_left);
  571.         else if (c == '>')
  572.             out_let(*cp++, np->n_right);
  573.         else if (c == '\'') {
  574.             c = *cp++;
  575.             fputc(c, output);
  576.         } else if (c == 'L')
  577.             seelab(*cp++, np);
  578.         else if (c == 'R')
  579.             seereg(np, *cp++);
  580.         else if (c >= 'A' && c <= 'Z') {
  581.             out_let(c, np);
  582.         } else
  583.             fputc(c, output);
  584. }
  585.  
  586. seereg(np, c)
  587. NODEP np;
  588. {
  589.     int i;
  590.  
  591.     switch (c) {
  592.     case '0':    i = np->g_rno;  break;
  593.     case '1':    i = np->g_r1;   break;
  594.     case '2':    i = np->g_r2;   break;
  595.     }
  596.     fprintf(output, regnm(i));    
  597. }
  598.  
  599. out_let(c, np)
  600. register NODEP np;
  601. {
  602.     int i;
  603.  
  604.     switch (c) {
  605.     case 'A':
  606.         if (np->g_flags & IMMEDID)
  607.             fputc('#', output);
  608.         out_a(np, output);
  609.         break;
  610.     case 'F':    /* branch if false */
  611.         i = cctok(np);
  612.         i = (i&1) ? i+1 : i-1;    /* reverse truth */
  613.         out_bnol(i);
  614.         break;
  615.     case 'K':
  616.         fprintf(output, "%ld", np->g_bsize);
  617.         break;
  618.     case 'N':
  619.         fprintf(output, "%s", np->n_name);
  620.         break;
  621.     case 'O':
  622.         fprintf(output, "%ld", np->g_offs);
  623.         break;
  624.     case 'Q':
  625.         if (np->g_flags & IMMEDID) {
  626.             warn("constant test expr");
  627.             if (np->g_token == ICON && np->g_offs == 0)
  628.                 fprintf(output, "\tor\t#$FF,ccr\n");
  629.             else
  630.                 fprintf(output, "\tand\t#0,ccr\n");
  631.             return;
  632.         }
  633.         fprintf(output, "\t%s.%c\t", isareg(np) ? "cmp" : "tst",
  634.             tlen(np->g_sz));
  635.         if (isareg(np))
  636.             fprintf(output, "#0,");
  637.         out_let('A', np);
  638.         fputc('\n', output);
  639.         break;
  640.     case 'S':
  641.         fputc(tlen(np->g_sz), output);
  642.         break;
  643.     case 'T':    /* branch if true */
  644.         out_bnol(cctok(np));
  645.         break;
  646.     case 'U':
  647.         fputc(np->g_ty == ET_U ? 'u' : 's', output);
  648.         break;
  649.     case 'W':    /* field width 1's */
  650.         fprintf(output, "$%x", ones(np->g_fldw));
  651.         break;
  652.     case 'X':    /* ~(W << offset) */
  653.         fprintf(output, "$%x", ~(ones(np->g_fldw)<<np->g_fldo));
  654.         break;
  655.     case 'Y':    /* field offset */
  656.         fprintf(output, "%d", np->g_fldo);
  657.         break;
  658.     case 'Z':    /* field offset - 8 */
  659.         fprintf(output, "%d", np->g_fldo - 8);
  660.         break;
  661.     default:
  662.         printf("bad out_let %c ", c);
  663.     }
  664. }
  665.  
  666. out_a(np, fd)
  667. register NODEP np;
  668. FILE *fd;
  669. {
  670.     int offs = np->g_offs;
  671.  
  672.     switch (np->g_token) {
  673.     case ICON:
  674.         fprintf(fd, "%ld", np->g_offs);
  675.         break;
  676.     case FCON:
  677.         /* works for ALCYON C */
  678.         /* otherwise depends on floating internal format */
  679.         fprintf(fd, "$%lx", np->g_offs);
  680.         break;
  681.     case ONAME:
  682.         while (np->g_flags & (CHILDNM|RCHILDNM)) {
  683.             np = (np->g_flags & CHILDNM) ? 
  684.                 np->n_left : np->n_right;
  685.         }
  686.         qput_nnm(np, fd);
  687.         if (offs)
  688.             fprintf(fd, offs > 0 ? "+%d" : "%d", offs);
  689.         break;
  690.     case PUSHER:
  691.         fprintf(fd, "(sp)+");
  692.         break;
  693.     case OREG:
  694.         if (offs)
  695.             fprintf(fd, "%d", offs);
  696.         fprintf(fd, "(%s)", regnm(np->g_rno));
  697.         break;
  698.     case REGVAR:
  699.         fprintf(fd, regnm(np->g_rno));
  700.         break;
  701.     case ',':
  702.         fputc(',', fd);        /* for debug */
  703.         break;
  704.     default:
  705.         if (np->g_token >= BR_TOK) {
  706.             fprintf(fd, "B_%s", bnm[np->g_token - BR_TOK]);
  707.             break;
  708.         }
  709.         printf("? tok %d ", np->g_token);
  710.     }
  711. }
  712.  
  713. seelab(c, np)
  714. char c;
  715. NODEP np;
  716. {
  717.     c -= '1';
  718.     fprintf(output, "L%d", (int)np->g_bsize+c);
  719. }
  720.  
  721. ones(n)
  722. {
  723.     return (1 << n) - 1;
  724. }
  725.     
  726.